package com.commons.base.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//获取 各种类型时间的 工具类
public class DateUtils {
	public static SimpleDateFormat yyyy_MM_dd__HH_mm_ss() {
		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	}

	public static SimpleDateFormat yyyy_MM_dd__00_00_00() {
		return new SimpleDateFormat("yyyy-MM-dd 00:00:00");
	};

	public static SimpleDateFormat yyyy_MM_dd__23_59_59() {
		return new SimpleDateFormat("yyyy-MM-dd 23:59:59");
	}

	public static SimpleDateFormat yyyy_MM_dd() {
		return new SimpleDateFormat("yyyy-MM-dd");
	}

	public static SimpleDateFormat yyyyMMddHHmmss() {
		return new SimpleDateFormat("yyyyMMddHHmmss");
	}

	public static SimpleDateFormat HH_mm_ss() {
		return new SimpleDateFormat("HH:mm:ss");
	}

	public static SimpleDateFormat yyyy__MM__dd___HH_mm_ss() {
		return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
	};

	public static SimpleDateFormat yyyy__MM__dd() {
		return new SimpleDateFormat("yyyy/MM/dd");
	}

	public static SimpleDateFormat yyyyMMdd() {
		return new SimpleDateFormat("yyyyMMdd");
	}

	public static SimpleDateFormat yyyy_MM() {
		return new SimpleDateFormat("yyyy-MM");
	};

	public static SimpleDateFormat yyyy() {
		return new SimpleDateFormat("yyyy");
	};

	public static SimpleDateFormat MM() {
		return new SimpleDateFormat("MM");
	};

	public static SimpleDateFormat dd() {
		return new SimpleDateFormat("dd");
	};

	public static SimpleDateFormat MM_dd() {
		return new SimpleDateFormat("MM-dd");
	};

	/**
	 * 传入 SimpleDateFormat 获得当前时间
	 * 
	 * @param format
	 * @return
	 */
	public static String getFormat(SimpleDateFormat format) {
		return convert_String(format, new Date());
	}

	public static String get_yyyy_MM_dd__HH_mm_ss() {
		return getFormat(yyyy_MM_dd__HH_mm_ss());
	}

	public static String get_yyyyMMdd() {
		return getFormat(yyyyMMdd());
	}

	public static String get_yyyy__MM__dd___HH_mm_ss() {
		return getFormat(yyyy__MM__dd___HH_mm_ss());
	}

	public static String get_yyyy_MM() {
		return getFormat(yyyy_MM());
	}

	public static String get_yyyy_MM(Date date) {
		return getFormat(yyyy_MM());
	}

	public static String get_yyyy_MM_dd() {
		return getFormat(yyyy_MM_dd());
	}

	public static String get_yyyyMMddHHmmss() {
		return getFormat(yyyyMMddHHmmss());
	}

	public static String get_yyyy_MM_dd__00_00_00() {
		return getFormat(yyyy_MM_dd__00_00_00());
	}

	public static String get_yyyy_MM_dd__23_59_59() {
		return getFormat(yyyy_MM_dd__23_59_59());
	}

	public static String get_yyyy() {
		return getFormat(yyyy());
	};

	public static String get_MM() {
		return getFormat(MM());
	};

	public static String get_dd() {
		return getFormat(dd());
	};

	public static String get_MM_dd() {
		return getFormat(MM_dd());
	};

	/**
	 * 字符串 时间 转换格式
	 * 
	 * @param old
	 *            数据原格式
	 * @param now
	 *            需要返回给你的格式
	 * @param data
	 *            数据
	 */
	public static String parse_Date(SimpleDateFormat oldF, SimpleDateFormat newF, String data) {
		try {
			return newF.format(oldF.parse(data));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return "";
	}

	/**
	 * 传入一个字符串时间和对应的类型 返回一个Date
	 * 
	 * @param fmt
	 *            格式（格式必须 与date类型的时间 格式 相等）
	 * @param date
	 *            Date类型的时间
	 * @return
	 */
	public static Date convert_date(SimpleDateFormat fmt, String date) {
		// 非空判断
		if (fmt == null || date == null) {
			return null;
		}

		try {
			return fmt.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 返回两个时间 的间隔 list(单位天)
	 * 
	 * @param startDate
	 *            格式必须是 yyyy_MM_dd
	 * @param endDate
	 *            格式必须是 yyyy_MM_dd
	 * @return
	 */
	// public static List<String> getTwoDateIntervalList(String startDate, String
	// endDate) {
	// // List<String> list = new ArrayList<>();
	// // Date startDateNew = convert_date(yyyy_MM_dd(), startDate);// 转 date
	// // Date endDateNew = convert_date(yyyy_MM_dd(), endDate);// 转 date
	// // if (startDateNew.getTime() == endDateNew.getTime()) {
	// // list.add(startDate);
	// // } else if (startDateNew.getTime() > endDateNew.getTime()) {
	// // long time = startDateNew.getTime() - endDateNew.getTime();
	// // int days = (int) (time / 1000 / 60 / 60 / 24);
	// // for (int i = 0; i <= days; i++) {
	// // Calendar calendar = Calendar.getInstance();
	// // calendar.setTime(startDateNew);
	// // calendar.add(Calendar.DAY_OF_MONTH, i * -1);
	// // list.add(convert_String(yyyy_MM_dd(), calendar.getTime()));
	// // }
	// // } else {
	// // long time = endDateNew.getTime() - startDateNew.getTime();
	// // int days = (int) (time / 1000 / 60 / 60 / 24);
	// // for (int i = 0; i <= days; i++) {
	// // Calendar calendar = Calendar.getInstance();
	// // calendar.setTime(startDateNew);
	// // calendar.add(Calendar.DAY_OF_MONTH, i);
	// // list.add(convert_String(yyyy_MM_dd(), calendar.getTime()));
	// // }
	// // }
	// return getTwoDateIntervalList(startDate, endDate, yyyy_MM_dd(),
	// Calendar.DAY_OF_MONTH);
	// }

	/**
	 * 返回两个时间 的间隔 list
	 * 
	 * @param startDate
	 * @param endDate
	 * @param format
	 *            startDate和endDate的格式
	 * @param type
	 *            计算类型 [GregorianCalendar.YEAR 0 年] [GregorianCalendar.MONTH 1 月]
	 *            [GregorianCalendar.DATE 2 日]
	 * @return
	 */
	public static List<Date> getTwoDateIntervalListDate(String startDate, String endDate, SimpleDateFormat format,
			int type) {
		List<String> list = getTwoDateIntervalListStr(startDate, endDate, format, type);
		List<Date> listDate = new ArrayList<>();
		for (int i = 0; i < list.size(); i++) {
			listDate.add(convert_date(format, list.get(i)));
		}
		return listDate;
	}

	public static List<String> getTwoDateIntervalListStr(String startDate, String endDate, SimpleDateFormat format,
			int type) {
		int index = 0;
		List<String> list = new ArrayList<>();
		Date startDateNew = convert_date(format, startDate);// 转 date
		Date endDateNew = convert_date(format, endDate);// 转 date
		if (startDateNew.getTime() == endDateNew.getTime()) {
			list.add(startDate);
		} else if (startDateNew.getTime() > endDateNew.getTime()) {
			while (true) {
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(startDateNew);
				calendar.add(type, index * -1);
				Date tmpDate = calendar.getTime();
				list.add(convert_String(format, tmpDate));
				if (endDateNew.getTime() == tmpDate.getTime()) {
					break;
				}
				index++;
			}
		} else {
			while (true) {
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(startDateNew);
				calendar.add(type, index * 1);
				Date tmpDate = calendar.getTime();
				list.add(convert_String(format, tmpDate));

				if (endDateNew.getTime() == tmpDate.getTime()) {
					break;
				}
				index++;
			}
		}
		return list;
	}

	/**
	 * 传入一个时间和对应的类型 返回一个String
	 * 
	 * @param fmt
	 *            格式
	 * @param date
	 *            Date类型的时间
	 * @return 格式化后的字符串
	 */
	public static String convert_String(SimpleDateFormat fmt, Date date) {
		// 非空判断
		if (fmt == null || date == null) {
			return null;
		}
		return fmt.format(date);
	}

	/**
	 * DateUtils.convert_Date_Date(DateUtils.yyyy_MM_dd__HH_mm_ss(),DateUtils.yyyy_MM_dd__00_00_00(),
	 * date) 传入一个时间和对应的类型 在返回date convert_Date_Date(yyyy_MM_dd__HH_mm_ss(),
	 * yyyy_MM_dd__23_59_59(), addDate(GregorianCalendar.DATE, 6,
	 * getTimesWeekmorning()))
	 * 
	 * @param fmt1
	 *            需要返回给你的格式（parse）
	 * @param fmt2
	 *            需要把date格式化的（format）
	 * @param date
	 *            Date类型的时间
	 * @return 格式化后的字符串
	 */
	public static Date convert_Date_Date(SimpleDateFormat fmt1, SimpleDateFormat fmt2, Date date) {
		try {
			return fmt1.parse(fmt2.format(date));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 当begin 比end 大 返回1 比end小返回-1 等于返回0
	 * 
	 * @param begin
	 * @param end
	 * @return
	 */
	public static int compareTo(Date begin, Date end) {
		if (begin.getTime() < end.getTime()) {
			return 1;
		} else if (begin.getTime() > end.getTime()) {
			return -1;
		}
		return 0;
	}

	/**
	 * 
	 * @param type
	 *            计算类型 [GregorianCalendar.YEAR 0 年] [GregorianCalendar.MONTH 1 月]
	 *            [GregorianCalendar.DATE 2 日]
	 * @param num
	 *            数量 （传负的就减）
	 * @param date
	 *            传入时间
	 * @return 得到的时间
	 */
	public static String addDate(int type, int num, Date date, SimpleDateFormat sf) {
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTime(date);
		cal.add(type, num);
		String time = sf.format(cal.getTime());
		return time;
	}

	public static Date addDate(int type, int num, Date date) {
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTime(date);
		cal.add(type, num);
		return cal.getTime();
	}

	/**
	 * 得到几天前的时间
	 * 
	 * @param d
	 * @param day
	 * @return
	 */
	public static Date getDateBefore(Date d, int day) {
		Calendar now = Calendar.getInstance();
		now.setTime(d);
		now.set(Calendar.DATE, now.get(Calendar.DATE) - day);
		return now.getTime();
	}

	/**
	 * 得到几天后的时间
	 * 
	 * @param d
	 * @param day
	 * @return
	 */
	public static Date getDateAfter(Date d, int day) {
		Calendar now = Calendar.getInstance();
		now.setTime(d);
		now.set(Calendar.DATE, now.get(Calendar.DATE) + day);
		return now.getTime();
	}

	/**
	 * 获得上个月的第一天日期
	 * 
	 * @param args
	 */
	public static Date getFirstDayOfLastMonth() {
		Calendar calendar = Calendar.getInstance();// 获取当前日期
		calendar.add(Calendar.MONTH, -1);
		calendar.set(Calendar.DAY_OF_MONTH, 1);// 设置为1号,当前日期既为本月第一天
		return calendar.getTime();
	}

	/**
	 * 获得上个月最后一天日期
	 * 
	 * @param args
	 */
	public static Date getLastDayOfLastMonth() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.add(Calendar.DATE, -1);
		return calendar.getTime();
	}

	/**
	 * 获取两个日期相差的月数
	 * 
	 * @param d1
	 *            较大的日期
	 * @param d2
	 *            较小的日期
	 * @return 如果d1>d2返回 月数差 否则返回0
	 */
	public static int getMonthDiff(Date d2, Date d1) {
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.setTime(d1);
		c2.setTime(d2);
		if (c1.getTimeInMillis() < c2.getTimeInMillis())
			return 0;
		int year1 = c1.get(Calendar.YEAR);
		int year2 = c2.get(Calendar.YEAR);
		int month1 = c1.get(Calendar.MONTH);
		int month2 = c2.get(Calendar.MONTH);
		int day1 = c1.get(Calendar.DAY_OF_MONTH);
		int day2 = c2.get(Calendar.DAY_OF_MONTH);
		// 获取年的差值 假设 d1 = 2015-8-16 d2 = 2011-9-30
		int yearInterval = year1 - year2;
		// 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
		if (month1 < month2 || month1 == month2 && day1 < day2)
			yearInterval--;
		// 获取月数差值
		int monthInterval = (month1 + 12) - month2;
		if (day1 < day2)
			monthInterval--;
		monthInterval %= 12;
		return yearInterval * 12 + monthInterval;
	}

	/**
	 * 获取当前月份最后一天
	 * 
	 * @return
	 */
	public static String getMonthLastDay() {
		// 获取当前年份、月份、日期
		Calendar cale = Calendar.getInstance();
		// 获取当月第一天和最后一天
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		// 获取前月的最后一天
		cale = Calendar.getInstance();
		cale.add(Calendar.MONTH, 1);
		cale.set(Calendar.DAY_OF_MONTH, 0);
		return format.format(cale.getTime());
	}

	/**
	 * 得到某个月的第一天和最后一天
	 * 
	 * @return
	 */
	public static Map<String, String> getMonthLimitDateMap(Date limitDate) {
		Map<String, String> dataMap = new HashMap<>();

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(limitDate);

		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		String firstDate = yyyy_MM_dd__00_00_00().format(calendar.getTime());
		dataMap.put("firstDate", firstDate);

		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		String lastDate = yyyy_MM_dd__23_59_59().format(calendar.getTime());
		dataMap.put("lastDate", lastDate);

		return dataMap;
	}

	public static Map<String, String> getDayLimitDateMap(Date limitDate) {
		Map<String, String> dataMap = new HashMap<>();

		dataMap.put("firstDate", convert_String(yyyy_MM_dd__00_00_00(), limitDate));

		dataMap.put("lastDate", convert_String(yyyy_MM_dd__23_59_59(), limitDate));

		return dataMap;
	}

	/**
	 * 获取当前月份第一天
	 * 
	 * @return
	 */
	public static String getMonthFirstDay() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		// 获取前月的第一天
		Calendar c = Calendar.getInstance();
		c.add(Calendar.MONTH, 0);
		c.set(Calendar.DAY_OF_MONTH, 1);// 设置为1号,当前日期既为本月第一天
		return format.format(c.getTime());
	}

	/**
	 * 获取上个月最后一天
	 * 
	 * @return
	 */
	public static String getLastMonthEndDay() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		// 获取前月的最后一天
		Calendar cale = Calendar.getInstance();
		cale.set(Calendar.DAY_OF_MONTH, 0);// 设置为1号,当前日期既为本月第一天
		return format.format(cale.getTime());
	}

	/**
	 * 判断给出的日期是星期几 这里要注意是闰年还是平年
	 * 
	 * @param date
	 * @return https://blog.csdn.net/liunian02050328/article/details/50886263
	 * @createTime 2016年3月14日
	 * @author hym
	 */
	public static String getWeekByDate(Date date) {
		if (date == null) {
			date = new Date();
		}
		int[] monthArr = new int[12];// 月代码
		if (isLeapYear(date)) {// 闰年
			monthArr = new int[] { 5, 1, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
		} else {// 平年
			monthArr = new int[] { 6, 2, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
		}
		String dateValue = formatDate(date, "yy,MM,dd");
		String[] year_month_day = dateValue.split(",");
		int year_code = Integer.parseInt(year_month_day[0]);
		int year_value = (year_code / 4 + year_code) % 7;// 年份代码，后两位数X除以4（忽略余数）,然后与X相加，并除以7就可以了，得到的余数就是其年份代码
		int month_value = monthArr[Integer.parseInt(year_month_day[1]) - 1];
		int day_value = Integer.parseInt(year_month_day[2]);
		return getweek((year_value + month_value + day_value) % 7);
	}

	private static String getweek(int weekvalue) {
		String week = null;
		switch (weekvalue) {
		case 0:
			week = "周日";
			break;
		case 1:
			week = "周一";
			break;
		case 2:
			week = "周二";
			break;
		case 3:
			week = "周三";
			break;
		case 4:
			week = "周四";
			break;
		case 5:
			week = "周五";
			break;
		case 6:
			week = "周六";
			break;

		default:
			break;
		}
		return week;
	}

	/**
	 * 格式化日期
	 * 
	 * @param date
	 * @param pattern
	 *            格式化后的日期格式
	 * @return
	 * @createTime 2016年3月14日
	 * @author hym
	 */
	private static String formatDate(Date date, String pattern) {// yyyy/MM/dd
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		return format.format(date);
	}

	/**
	 * 判断是否为闰年 闰年返回true
	 * 
	 * @param date
	 * @return
	 * @createTime 2016年3月14日
	 * @author hym
	 */
	private static boolean isLeapYear(Date date) {
		// 1.能被400整除的年份； 2.能被4整除但同时不能被100整除的年份 满足之一即是闰年
		Integer year = Integer.parseInt(formatDate(date, "yyyy"));
		return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
	}

	public static String getMonthStrByDate(Date date) {
		String monthStr = "";
		switch (convert_String(MM(), date)) {
		case "01":
			monthStr = "一月";
			break;
		case "02":
			monthStr = "二月";
			break;
		case "03":
			monthStr = "三月";
			break;
		case "04":
			monthStr = "四月";
			break;
		case "05":
			monthStr = "五月";
			break;
		case "06":
			monthStr = "六月";
			break;
		case "07":
			monthStr = "七月";
			break;
		case "08":
			monthStr = "八月";
			break;
		case "09":
			monthStr = "九月";
			break;
		case "10":
			monthStr = "十月";
			break;
		case "11":
			monthStr = "十一月";
			break;
		case "12":
			monthStr = "十二月";
			break;
		}
		return monthStr;
	}

	// 获得本周一0点时间 https://blog.csdn.net/whzhaochao/article/details/40186805
	public static Date getTimesWeekmorning() {
		Calendar cal = Calendar.getInstance();
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		return cal.getTime();
	}

	// 获得本周日24点时间 https://blog.csdn.net/whzhaochao/article/details/40186805
	public static Date getTimesWeeknight() {
		return convert_Date_Date(yyyy_MM_dd__HH_mm_ss(), yyyy_MM_dd__23_59_59(),
				addDate(GregorianCalendar.DATE, 6, getTimesWeekmorning()));
	}

	public static void main(String[] args) {
		System.out.println(getTimesWeeknight());
	}
}
